import config.ConfigLoader;
import lombok.extern.log4j.Log4j;
import register.ServiceRegistry;
import entity.RemoteCall;

import java.io.*;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Log4j
public class Server {

    private static final ExecutorService SERVER_EXECUTOR = Executors.newFixedThreadPool(10); // 设置线程池大小为10个线程

    public static void main(String args[]) throws IOException {
        ConfigLoader configLoader = new ConfigLoader("config.yml");
        Server server = new Server();
        ServiceRegistry.initialize(ConfigLoader.getRegistryHost()+":"+ConfigLoader.getRegistryPort());;
        ServiceRegistry.scanAndRegisterServices();
        server.service();
    }

    public void service() {
        try {
            ServerSocket serverSocket = new ServerSocket(8000);
            log.info("服务启动......");
            System.out.println(" 服务器启动......");
            while (true) {
                try {
                    final Socket client = serverSocket.accept();
                    SERVER_EXECUTOR.execute(() -> handleClient(client));
                } catch (IOException e) {
                    log.error("接受请求失败: " + e.getMessage());
                }
            }
        } catch (IOException e) {
            log.error("ServerSocket 初始化失败: " + e.getMessage());
        }
    }

    private void handleClient(Socket client) {
        // 2.1 获取客户端ip前缀
        String clientAddress = client.getInetAddress().getHostAddress();
        // 2.2 输出客户端连接状态
        log.debug("客户端连接成功: " + clientAddress);
        System.out.println(clientAddress + " 已连接");
        try {
            InputStream in = client.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(in);
            OutputStream out = client.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(out);
            //接收客户发送的Call 对象
            RemoteCall remotecallobj = (RemoteCall) ois.readObject();

            log.debug("接收到客户端的调用请求: " + remotecallobj);
            remotecallobj = invoke(remotecallobj);
            // 向客户发送包含了执行结果的remotecallobj 对象
            oos.writeObject(remotecallobj);
            ois.close();
            oos.close();
            client.close();
        } catch (Exception e) {
            log.error("处理请求失败: " + e.getMessage());
        }
    }
    public RemoteCall invoke(RemoteCall call) {
        Object result = null;
        try {
            String className = call.getClassName();
            String methodName = call.getMethodName();
            Object[] params = call.getParams();
            Class<?> classType = Class.forName(className);
            Class<?>[] paramTypes = call.getParamTypes();
            Method method = classType.getMethod(methodName, paramTypes);
            // 从缓存中取出相关的远程对象Object
            Object remoteObject = ServiceRegistry.REMOTE_OBJECTS.get(className);
            if (remoteObject == null) {
                System.out.println("远程对象不存在: " + className);
                log.error("远程对象不存在: " + className);
            } else {
                result = method.invoke(remoteObject, params);
                log.debug("远程调用结束:remotObject:" + remoteObject.toString() + ",params:" + params.toString());
            }
        } catch (Exception e) {
            log.error("远程调用失败: " + e.getMessage());
            result = null;
        }
        call.setResult(result);

        return call;
    }

}